package com.cloudbroker.bsc.common.search.common;

import com.cloudbroker.bcs.common.util.StringUtil;
import com.cloudbroker.bsc.common.search.exception.SearchEngineErrorCode;
import com.cloudbroker.bsc.common.search.exception.SearchEngineException;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by moyin18602 on 2016/6/14.
 */
public class SearchEngineUtil {
    /**
     *
     * @param map
     * @return
     */
    public static QueryBuilder mapToQueryBuilder(Map<String,String> map){
        String regex_range = "^es range .*";
        String regex_equals = "^es equals .*";
        String regex_should = "^es should .*";
        BoolQueryBuilder bqb = QueryBuilders.boolQuery();
        for (Map.Entry<String, String> entry : map.entrySet()) {
        	if(null == entry.getKey()){
            	bqb.must(QueryBuilders.queryStringQuery(entry.getValue()));
            }
            // 范围查询
        	else if(entry.getValue().matches(regex_range)){
                if(StringUtil.isEmpty(entry.getValue().substring(regex_range.length()-2,entry.getValue().length()))){
                    throw new SearchEngineException(SearchEngineErrorCode.formatErr.PARAM_LENGTH);
                }
                String[] values = entry.getValue().substring(regex_range.length()-3,entry.getValue().length()).split(" ");
                if(values.length == 1){
                    bqb.must(QueryBuilders.rangeQuery(entry.getKey()).gte(values[0]));
                }else if(values.length == 2){
                    bqb.must(QueryBuilders.rangeQuery(entry.getKey()).gt(Double.parseDouble(values[0])).lt(Double.parseDouble(values[1])));
                }

            }
            // 精确查询
            else if(entry.getValue().matches(regex_equals)){
                if(StringUtil.isEmpty(entry.getValue().substring(regex_range.length()-2,entry.getValue().length()))){
                    throw new SearchEngineException(SearchEngineErrorCode.formatErr.PARAM_LENGTH);
                }
                String value = entry.getValue().substring(10,entry.getValue().length());
                bqb.must(QueryBuilders.termQuery(entry.getKey(), value));
            }
            //组合表达式   name == 1 or age == 23
            else if(entry.getValue().matches(regex_should)){
                BoolQueryBuilder bqb_should = QueryBuilders.boolQuery();
                String value = entry.getValue().substring(10,entry.getValue().length());
                String[] expression = value.split(" or ");

                List<String> ex_list = new ArrayList();
                for (String ex : expression) {
                    String[] value_and = ex.split(" and ");
                    if(value_and.length > 1){
                            ex_list.add("or " + value_and[0]);
                            ex_list.add("and " + value_and[1]);
                    }else{
                        ex_list.add("or " + value_and[0]);
                    }
                }

                for (String s : ex_list) {
                    if(s.indexOf("or ") != -1){
                        s = s.replace("or ","");
                        s = s.replace(" ","");
                        String[] params = s.split("==");
                        bqb_should.should(new QueryStringQueryBuilder(params[1]).field(params[0]));
                    }else if(s.indexOf("and ") != -1){
                        s = s.replace("and ","");
                        s = s.replace(" ","");
                        String[] params = s.split("==");
                        bqb_should.must(new QueryStringQueryBuilder(params[1]).field(params[0]));
                    }
                }
                bqb.must(bqb_should);
            }else{
                bqb.must(QueryBuilders.regexpQuery(entry.getKey(), "**"+entry.getValue()+"**"));
            }

        }
        return bqb;
    }

    /**
     *
     * @param hits
     * @return
     */
    public static List<Map> searchHistsToList(SearchHits hits){
        long total = hits.getTotalHits();
        SearchHit[] searchHists = hits.getHits();
        List<Map> l = new ArrayList();
        if (searchHists.length > 0) {
            for (SearchHit hit : searchHists) {
                Map m = hit.getSource();
                m.put("database_name",hit.getIndex());
                m.put("table_name",hit.getType());
                m.put("row_id",hit.getId());
                m.put("total",total);
                l.add(m);
            }
        }
        return l;
    }
}
